/*
 * AbstractController.java
 * Copyright (c) Faculdade Anhanguera de Anápolis.
 * Tecnologia em Análise e Desenvolvimento de Sistemas.
 * Projeto Multidisciplinar de Autoaprendizagem.
 *
 * Este software é confidencial e propriedade da Faculdade Anhanguera de Anápolis.
 * Não é permitida sua distribuição ou divulgação do seu conteúdo sem expressa autorização da Faculdade Anhanguera de Anápolis.
 * Este arquivo contém informações proprietárias.
 */package br.com.pma.chamatec.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Locale;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import br.com.pma.chamatec.dominio.ContentTypeArquivo;
import br.com.pma.chamatec.exception.ChamatecExceptionCode;
import br.com.pma.chamatec.security.UsuarioBean;
import br.com.pma.chamatec.util.ChamatecResource;
import br.com.pma.chamatec.util.EnumResources;
import br.com.pma.chamatec.vo.AtributosRelatorioVO;

/**
 * Classe padrão de controlador.
 * 
 * @author Ludemeula Fernandes de Sá
 */
public abstract class AbstractController implements Serializable {
	private static final long serialVersionUID = 1630414283866806396L;

	@Inject
	private Conversation conversation;

	@Inject
	protected Logger log;

	@Inject
	protected ChamatecResource resource;

	@Inject
	protected FacesContext facesContext;

	@Inject
	protected UsuarioBean usuarioBean;

	private Boolean mostraCadastro = false;
	private Boolean isCadastro = false;
	private Boolean isErro = false;
	
	/**
	 * Método de inicialização do formulário.
	 */
	@PostConstruct
	public void init() {
		facesContext.getExternalContext().getSession(true);
	}

	/**
	 * Inicia uma conversação.
	 */
	protected void beginConversation() {
		if (conversation.isTransient()) {
			conversation.begin();
		}
	}

	/**
	 * Inicia uma conversação.
	 * 
	 * @param name
	 */
	protected void beginConversation(String name) {
		if (conversation.isTransient()) {
			conversation.begin(name);
		}
	}

	/**
	 * Finaliza uma conversação.
	 */
	public void endConversation() {
		if (!conversation.isTransient()) {
			conversation.end();
		}
	}

	/**
	 * Adiciona uma mensagem para exibição nas páginas.
	 * 
	 * @param resource
	 */
	protected void addFacesMessage(EnumResources resource) {
		addFacesMessage(resource, FacesMessage.SEVERITY_INFO);
	}

	/**
	 * Adiciona uma mensagem para exibição nas páginas.
	 * 
	 * @param code
	 * @param severity
	 */
	protected void addFacesMessage(EnumResources code, Severity severity) {
		String msg = resource.getMessage(code);
		addFacesMessage(msg, severity);
	}

	/**
	 * Adiciona uma mensagem para exibição nas páginas.
	 * 
	 * @param code
	 * @param severity
	 */
	protected void addFacesMessage(ChamatecExceptionCode code, Severity severity) {
		String msg = resource.getMessage(code);
		addFacesMessage(msg, severity);
	}

	/**
	 * Adiciona uma mensagem para exibição nas páginas.
	 * 
	 * @param msg
	 */
	protected void addFacesMessage(String msg) {
		addFacesMessage(msg, FacesMessage.SEVERITY_INFO);
	}

	/**
	 * Adiciona uma mensagem para exibição nas páginas.
	 * 
	 * @param msg
	 * @param severity
	 */
	protected void addFacesMessage(String msg, Severity severity) {
		facesContext.addMessage(null, new FacesMessage(severity, msg, msg));
	}

	/**
	 * Recupera o diretorio onde o sistema esta instalado.
	 * 
	 * @return
	 */
	protected String recuperarPathAplicacao() {
		return ((ServletContext) facesContext.getExternalContext().getContext()).getRealPath("/");
	}

	/**
	 * Recupera um valor do request pelo parametro informado.
	 * 
	 * @param parameter
	 * @return
	 */
	protected String getRequestParameter(String parameter) {
		HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
		return request.getParameter(parameter);
	}

	/**
	 * Adiciona um objeto a sessão.
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	protected void addSessionAttribuite(String key, Object value) {
		HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
		request.getSession().setAttribute(key, value);
	}

	/**
	 * Recupera um objeto a sessão.
	 * 
	 * @param key
	 * @return
	 */
	protected Object getSessionAttribuite(String key) {
		HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
		Object retorno = request.getSession().getAttribute(key);
		if (retorno != null) {
			request.getSession().removeAttribute(key);
		}
		return retorno;
	}

	/**
	 * Envia para a página de pesquisa.
	 */
	public String voltar() {
		return "index.jsf?faces-redirect=true";
	}
	
	/**
	 * Configura a exibição da tela de cadastro para ser exibida.
	 */
	protected void mostraCadastro() {
		setMostraCadastro(true);
	}

	/**
	 * Configura a exibição da tela de cadastro para ser escondida.
	 */
	protected void escondeCadastro() {
		setMostraCadastro(false);
	}

	/**
	 * Monta a mensagem de erro para as mensagens não tratadas da aplica��o.
	 * 
	 * @param e
	 */
	protected void montaMensagemGenerica(Exception e) {
		StringBuilder msg = new StringBuilder();
		msg.append(resource.getMessage(ChamatecExceptionCode.MI_002) + "  ");
		msg.append("Descrição do erro: " + e.getMessage());
		addFacesMessage(msg.toString(), FacesMessage.SEVERITY_ERROR);
	}

	/**
	 * Gera um relatório utilizando o JasperReports.
	 * 
	 * @param facesContext
	 * @param atributosGeracao
	 * @param contentType
	 * @throws IOException
	 * @throws JRException
	 */
	protected void gerarRelatorio(FacesContext facesContext, AtributosRelatorioVO atributosGeracao, ContentTypeArquivo contentType) throws IOException, JRException {
		JRAbstractExporter exporter = processarRelatorio(atributosGeracao, contentType);
		processarArquivoJasper(facesContext, exporter, contentType, atributosGeracao);
	}

	/**
	 * Realiza o processamento de um relatório Jasper.
	 * 
	 * @param atributosGeracao
	 * @param contentType
	 * @return
	 * @throws JRException
	 */
	private JRAbstractExporter processarRelatorio(AtributosRelatorioVO atributosGeracao, ContentTypeArquivo contentType) throws JRException {
		JasperPrint jasperPrint = null;
		InputStream arquivoJasper = null;
		Locale ptBr = new Locale("pt", "BR");
		JRAbstractExporter exporter = null;
		JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(atributosGeracao.getColecao());

		if (atributosGeracao.isCompilar()) {
			arquivoJasper = Thread.currentThread().getContextClassLoader().getResourceAsStream(atributosGeracao.getNomeArquivoJasper().replaceAll("jasper", "jrxml"));
			jasperPrint = JasperFillManager.fillReport(JasperCompileManager.compileReport(arquivoJasper), atributosGeracao.getParams(), dataSource);
		} else {
			arquivoJasper = Thread.currentThread().getContextClassLoader().getResourceAsStream(atributosGeracao.getNomeArquivoJasper());
			jasperPrint = JasperFillManager.fillReport(arquivoJasper, atributosGeracao.getParams(), dataSource);
		}

		jasperPrint.setLocaleCode(ptBr.getCountry());
		if (contentType.equals(ContentTypeArquivo.PDF)) {
			exporter = new JRPdfExporter();
		} else if (contentType.equals(ContentTypeArquivo.CSV)) {
			exporter = new JRCsvExporter();
			exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, ";");
			exporter.setParameter(JRCsvExporterParameter.CHARACTER_ENCODING, "ISO-8859-1");
		} else if (contentType.equals(ContentTypeArquivo.HTML)) {
			exporter = new JRHtmlExporter();
			exporter.setParameter(JRHtmlExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
			exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);
			exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "ISO-8859-1");
		}
		exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

		return exporter;
	}

	/**
	 * Prepara o relatório do Jasper para ser realizado o download.
	 * 
	 * @param facesContext
	 * @param exporter
	 * @param contentType
	 * @param nomeArquivoGeracao
	 * @throws IOException
	 * @throws JRException
	 */
	private void processarArquivoJasper(FacesContext facesContext, JRExporter exporter, ContentTypeArquivo contentType, AtributosRelatorioVO atributosGeracao) throws IOException, JRException {
		HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
		response.setContentType(contentType.getDefinicao());
		if (atributosGeracao.isModoDownload()) {
			response.addHeader("Content-disposition", "attachment; filename=\"" + atributosGeracao.getNomeArquivoGeracao() + contentType.getExtensao() + "\"");
		}
		if (contentType.equals(ContentTypeArquivo.CSV)) {
			response.setContentType(ContentTypeArquivo.CSV.getDefinicao() + "; charset=ISO-8859-1");
			response.setCharacterEncoding("ISO-8859-1");
		}
		ServletOutputStream os = response.getOutputStream();

		exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, os);
		exporter.exportReport();

		os.flush();
		os.close();
		facesContext.responseComplete();
	}

	/********************************************* Getters e Setters *****************************************************/
	/**
	 * @return the conversation
	 */
	public Conversation getConversation() {
		return conversation;
	}

	/**
	 * @return the log
	 */
	public Logger getLog() {
		return log;
	}

	/**
	 * @return the resource
	 */
	public ChamatecResource getResource() {
		return resource;
	}

	/**
	 * @return the facesContext
	 */
	public FacesContext getFacesContext() {
		return facesContext;
	}

	/**
	 * @return the usuarioBean
	 */
	public UsuarioBean getUsuarioBean() {
		return usuarioBean;
	}

	/**
	 * @return the mostraCadastro
	 */
	public Boolean getMostraCadastro() {
		return mostraCadastro;
	}

	/**
	 * @param mostraCadastro the mostraCadastro to set
	 */
	public void setMostraCadastro(Boolean mostraCadastro) {
		this.mostraCadastro = mostraCadastro;
	}

	/**
	 * @return the isCadastro
	 */
	public Boolean getIsCadastro() {
		return isCadastro;
	}

	/**
	 * @param isCadastro the isCadastro to set
	 */
	public void setIsCadastro(Boolean isCadastro) {
		this.isCadastro = isCadastro;
	}

	/**
	 * @return the isErro
	 */
	public Boolean getIsErro() {
		return isErro;
	}

	/**
	 * @param isErro the isErro to set
	 */
	public void setIsErro(Boolean isErro) {
		this.isErro = isErro;
	}
}